using System;
using System.Collections.Generic;
using System.Text;

using System.Drawing;
using System.Drawing.Drawing2D;
using System.ComponentModel;

using Athena.Core;

namespace Athena.Objects
{
    [Serializable()]
    public class PromoterGlyph : PartGlyph
    {

        /// <summary>
        /// Initializes a new instance of the SimpleBox class.
        /// </summary>
        /// <param name="location"></param>
        public PromoterGlyph(PointF location)
        {
            TextH = HorizontalAlignment.Center;
            TextV = VerticalAlignment.BelowBottom;
            _Location = location;
            _Dimensions = new SizeF(60, 46);

            _oFillColorStart = Color.White;
            _oFillColorEnd = Color.SteelBlue;
            _oPartColor = Color.Green;
            _oEdgeColor = Color.Black;

            //DNAGlyph ParentDNA = Program.Model.FindDNA(location);            
            Item = new Promoter("Promoter_0", "TATAATTGAATCA");
            ((Part)Item).PoPS.Rate = "10";  //basal
            ((Part)_Item).OutputConnectionsAllowed = false;
        }
        public PromoterGlyph()
        {
            _Location = new PointF(0, 0);
            _Dimensions = new SizeF(20, 20);
            Name = "Promoter_0";
            _oPartColor = Color.Green;
            _oEdgeColor = Color.Black;
            _Item = new Promoter();
        }
        public override object Clone()
        {
            return new PromoterGlyph(this);
        }

        public PromoterGlyph(PromoterGlyph copy)
            : base(copy)
        {

        }
        public override Bitmap GetPreview(int width, int height)
        {
            Bitmap oBitmap = new Bitmap(width, height);
            Graphics g = Graphics.FromImage(oBitmap);

            RenderIcon(g, width, height);

            return oBitmap;
        }

        public override void RenderIcon(Graphics g, float width, float height)
        {
            Pen oOutline = new Pen(_oEdgeColor, 0.5f);
            Brush oFilled = new SolidBrush(_oPartColor);

            GraphicsPath oPath;

            switch (View)
            {
                case ViewType.Schematic:
                    oPath = (GraphicsPath)CreateSchematicPath(width, height);
                    break;
                default:
                    oPath = (GraphicsPath)_oBlockPath.Clone();
                    break;
            }

            RectangleF pathBounds = _oBlockPath.GetBounds();


            Matrix oTransform = new Matrix();

            oTransform.Scale(
                   0.8f * width / pathBounds.Width,
                   0.8f * height / pathBounds.Height, MatrixOrder.Prepend);
            oTransform.Translate(1f, 1f);

            oPath.Transform(oTransform);

            g.DrawPath(oOutline, oPath);

            if (View == ViewType.Block)
            {
                g.FillPath(oFilled, oPath);
                GraphicsPath oPathShine = (GraphicsPath)_oPathShine.Clone();
                oPathShine.Transform(oTransform);
                g.DrawPath(new Pen(Color.White, 1), oPathShine);
            }
        }

        static GraphicsPath _oBlockPath = CreateBlockPath(), _oPathShine = ShiningLine();

        static GraphicsPath CreateSchematicPath(float w, float h)
        {
            GraphicsPath oPath = new GraphicsPath();

            oPath.AddLine(w / 4, h, w / 4, h / 2);
            oPath.AddLine(w / 4, h / 2, 3 * w / 4, h / 2);
            oPath.AddLine(3 * w / 4, h / 2, 3 * w / 4, h);

            oPath.AddLine(0f, h, w, h);
            oPath.AddLine(w, h, w, 2);
            //oPath.AddLine(w, h / 2, w + 10, h / 2);
            oPath.AddLine(w + 18, 2, w + 17, 0);
            //oPath.AddLine(w + 10, h / 2 - 5f, w + 20, h / 2);
            oPath.AddLine(w + 20, 2, w + 17, 4f);
            oPath.AddLine(w + 17, 4f, w + 18, 2);
            //oPath.AddLine(w + 20, h / 2, w, h / 2);
            oPath.AddLine(w, 2, w, h);
            //oPath.AddLine(w, h, w, h);
            oPath.CloseFigure();

            return oPath;
        }

        public override SBMLExtension.EmlRenderExtension.LocalStyle ToStyle(SBMLExtension.EmlRenderExtension.RenderInformation oInfo)
        {

            SBMLExtension.EmlRenderExtension.LocalStyle oResult = new SBMLExtension.EmlRenderExtension.LocalStyle();
            SBMLExtension.EmlRenderExtension.Group oGroup = new SBMLExtension.EmlRenderExtension.Group();
            oGroup.Stroke = oInfo.AddColorDefinition(_oEdgeColor);
            oGroup.StrokeWidth = _dEdgeThickness.ToString();
            if (_oFillColorStart == _oFillColorEnd)
                oGroup.Fill = oInfo.AddColorDefinition(_oFillColorStart);
            else
                oGroup.Fill = oInfo.AddLinearGradientDefinition(_oFillColorStart, _oFillColorEnd);


            oGroup.Children.Add(new SBMLExtension.EmlRenderExtension.Rectangle());

            SBMLExtension.EmlRenderExtension.Polygon oPolygon = new SBMLExtension.EmlRenderExtension.Polygon();
            oPolygon.Fill = oInfo.AddColorDefinition(PartColor);
            oPolygon.Stroke = oGroup.Stroke;
            oPolygon.StrokeWidth = oGroup.StrokeWidth;

            oPolygon.CurveSegments.Add(new SBMLExtension.LayoutExtension.CurveSegment(
                new SBMLExtension.LayoutExtension.Point(0f, 20f),
                new SBMLExtension.LayoutExtension.Point(0f, 10f)
                ));
            //oPath.AddArc(0F, 3F, 5f, 3f, 180f, 90f);
            oPolygon.CurveSegments.Add(new SBMLExtension.LayoutExtension.CurveSegment( // this should be an arc:
                new SBMLExtension.LayoutExtension.Point(0f, 10f),
                new SBMLExtension.LayoutExtension.Point(5f, 3f),
                new SBMLExtension.LayoutExtension.Point(0f, 3f), // base 1
                new SBMLExtension.LayoutExtension.Point(0f, 3f) // base 2
                ));
            oPolygon.CurveSegments.Add(new SBMLExtension.LayoutExtension.CurveSegment(
                new SBMLExtension.LayoutExtension.Point(5f, 3f),
                new SBMLExtension.LayoutExtension.Point(10f, 3f)
                ));
            oPolygon.CurveSegments.Add(new SBMLExtension.LayoutExtension.CurveSegment(
                new SBMLExtension.LayoutExtension.Point(10f, 3f),
                new SBMLExtension.LayoutExtension.Point(10f, 0f)
                ));
            oPolygon.CurveSegments.Add(new SBMLExtension.LayoutExtension.CurveSegment(
                new SBMLExtension.LayoutExtension.Point(10f, 0f),
                new SBMLExtension.LayoutExtension.Point(13f, 5f)
                ));
            oPolygon.CurveSegments.Add(new SBMLExtension.LayoutExtension.CurveSegment(
                new SBMLExtension.LayoutExtension.Point(13f, 5f),
                new SBMLExtension.LayoutExtension.Point(10f, 10f)
                ));
            oPolygon.CurveSegments.Add(new SBMLExtension.LayoutExtension.CurveSegment(
                new SBMLExtension.LayoutExtension.Point(10f, 10f),
                new SBMLExtension.LayoutExtension.Point(10f, 7f)
                ));
            oPolygon.CurveSegments.Add(new SBMLExtension.LayoutExtension.CurveSegment(
                new SBMLExtension.LayoutExtension.Point(10f, 7f),
                new SBMLExtension.LayoutExtension.Point(5f, 7f)
                ));

            
            // oPath.AddArc(3F, 7F, 2f, 3f, -90f, -90f);
            oPolygon.CurveSegments.Add(new SBMLExtension.LayoutExtension.CurveSegment( // arc
                    new SBMLExtension.LayoutExtension.Point(5f, 7f),
                    new SBMLExtension.LayoutExtension.Point(3f, 10f),
                    new SBMLExtension.LayoutExtension.Point(3f, 7f),
                    new SBMLExtension.LayoutExtension.Point(3f, 7f)
                    ));
            oPolygon.CurveSegments.Add(new SBMLExtension.LayoutExtension.CurveSegment(
                    new SBMLExtension.LayoutExtension.Point(3f, 10f),
                    new SBMLExtension.LayoutExtension.Point(3f, 20f)
                    ));


            float dScaleX = 0.70f * _Dimensions.Width / 13f;
            float dScaleY = 0.70f * _Dimensions.Height / 20f;

            float dOffsetX = 0.5f * _Dimensions.Width - 13f * dScaleX / 2;
            float dOffsetY = 0.5f * _Dimensions.Height - 20f * dScaleY / 2;

            oPolygon.Transform = dScaleX.ToString() + ",0,0," + dScaleY.ToString() + "," + dOffsetX.ToString() + "," + dOffsetY.ToString();

            oGroup.Children.Add(oPolygon);


            if (!string.IsNullOrEmpty(Text) && ShowText)
            {
                SBMLExtension.EmlRenderExtension.Text oText = new SBMLExtension.EmlRenderExtension.Text();
                oText.FontFamily = TextFont.FontFamily.Name;
                oText.FontSize = TextFont.SizeInPoints.ToString();
                oText.Stroke = oInfo.AddColorDefinition(TextColor);
                if (TextFont.Bold) oText.FontWeight = SBMLExtension.EmlRenderExtension.Text.FontWeiths.bold.ToString();
                if (TextFont.Italic) oText.FontStyle = SBMLExtension.EmlRenderExtension.Text.FontStyles.italic.ToString();
                oText.StrokeWidth = "1";
                oText.Y = "130%";
                oText.X = "-50%";
                oText.TheText = Text;
                oGroup.Children.Add(oText);
            }
            oResult.Group = oGroup;
            return oResult;
        }
        static GraphicsPath CreateBlockPath()
        {
            GraphicsPath oPath = new GraphicsPath();

            oPath.AddLine(0f, 20f, 0f, 10f);
            oPath.AddArc(0F, 3F, 5f, 3f, 180f, 90f);
            oPath.AddLine(5f, 3f, 10f, 3f);
            oPath.AddLine(10f, 3f, 10f, 0f);
            oPath.AddLine(10f, 0f, 13f, 5f);
            oPath.AddLine(13f, 5f, 10f, 10f);
            oPath.AddLine(10f, 10f, 10f, 7f);
            oPath.AddLine(10f, 7f, 5f, 7f);
            oPath.AddArc(3F, 7F, 2f, 3f, -90f, -90f);
            oPath.AddLine(3f, 10f, 3f, 20f);
            oPath.CloseFigure();

            return oPath;
        }

        static GraphicsPath ShiningLine()
        {
            GraphicsPath oPath = new GraphicsPath();

            oPath.AddLine(1f, 15f, 1f, 11f);
            oPath.AddArc(1F, 4F, 4f, 3f, 180f, 90f);
            oPath.AddLine(6f, 4f, 10f, 4f);

            return oPath;
        }

        public override void RenderGlyph(Graphics g)
        {
            Pen oOutline = new Pen(_oEdgeColor, _dEdgeThickness);
            Brush oFilled = new SolidBrush(_oPartColor);
            //Brush oFilled = new LinearGradientBrush(Location, new PointF(Location.X + Dimensions.Width, Location.Y + Dimensions.Height), Color.White, _oFillColor);

            GraphicsPath oPath;
            float w, h;

            switch (View)
            {
                case ViewType.Schematic:
                    w = _Dimensions.Width;
                    h = _Dimensions.Height;
                    oPath = (GraphicsPath)CreateSchematicPath(w + 5, h);
                    break;
                default:
                    DrawBox(g);
                    oPath = (GraphicsPath)_oBlockPath.Clone();
                    w = h = 0.5f * Math.Min(_Dimensions.Height, _Dimensions.Width);
                    break;
            }

            RectangleF pathBounds = _oBlockPath.GetBounds();

            Matrix oTransform = new Matrix();

            if (Direction == Part.Orientation.forward)
            {
                if (View != ViewType.Schematic)
                {
                    oTransform.Scale(
                         w / pathBounds.Width,
                         h / pathBounds.Height, MatrixOrder.Prepend);
                }
                oTransform.Translate(
                    0.5f * _Dimensions.Width + _Location.X - w / 2,
                    0.5f * _Dimensions.Height + _Location.Y - h / 2,
                    MatrixOrder.Append);
            }
            else
            {
                if (View != ViewType.Schematic)
                {
                    oTransform.Scale(
                       -w / pathBounds.Width,
                        h / pathBounds.Height, MatrixOrder.Prepend);
                }
                else
                {
                    oTransform.Scale(-1, 1, MatrixOrder.Prepend);
                }
                oTransform.Translate(
                    0.5f * _Dimensions.Width + _Location.X + w / 2,
                    0.5f * _Dimensions.Height + _Location.Y - h / 2,
                    MatrixOrder.Append);
            }

            oPath.Transform(oTransform);

            if (View == ViewType.Schematic)
                g.FillPath(new SolidBrush(_oFillColorEnd), oPath);

            g.DrawPath(oOutline, oPath);

            if (View == ViewType.Block)
            {
                GraphicsPath oPathShine = (GraphicsPath)_oPathShine.Clone();
                g.FillPath(oFilled, oPath);
                oPathShine.Transform(oTransform);
                g.DrawPath(new Pen(Color.White, w / 20), oPathShine);
            }
        }

        public override bool HasPreview
        {
            get
            {
                return true;
            }
        }
    }
}
